package com.ilarele.shopping.client.database;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.util.Log;

public class ShoppingDB extends ContentProvider {
	private static final String TAG = "ShoppingDB";

	// db
	private static final String AUTHORITY = "com.ilarele.shopping.client.database";
	private static final int DATABASE_VERSION = 9;
	private static final String DATABASE_NAME = "shoppingDB.db";

	// table Products - my filled data
	private static final String TABLE_PROD = "products";
	public static final String CONTENT_TYPE_PROD = "products";
	public static final String PRODUCT_ID = "_id";
	public static final String PICTURE = "picture";
	public static final String NAME = "name";
	public static final String LOCATION_NAME = "location";
	public static final String LOCATION_LAT = "latitude";
	public static final String LOCATION_LONG = "longitude";
	public static final String PRICE = "price";
	public static final String RATING = "rating";
	public static final String TAGS = "tags";

	// table RatedPictures
	private static final String TABLE_RATED_PICTURES = "rated_pictures";
	public static final String CONTENT_TYPE_PICTURES = "pictures";
	public static final String RATED_PICTURES_ID = "_id";
	public static final String RATED_PICTURES_VALUE = "value";

	// table RatedNames
	private static final String TABLE_RATED_NAMES = "rated_names";
	public static final String CONTENT_TYPE_NAMES = "names";
	public static final String RATED_NAMES_ID = "_id";
	public static final String RATED_NAMES_VALUE = "value";

	// table RatedInfo
	private static final String TABLE_RATED_INFO = "rated_info";
	public static final String CONTENT_TYPE_INFO = "info";
	public static final String RATED_INFO_ID = "_id";
	public static final String RATED_INFO_VALUE = "value";

	// table RatedTags
	private static final String TABLE_RATED_TAGS = "rated_tags";
	public static final String CONTENT_TYPE_TAGS = "tags";
	public static final String RATED_TAGS_ID = "_id";
	public static final String RATED_TAGS_VALUE = "value";

	// CONTENT_URI
	public static final Uri CONTENT_URI_RATED_PICTURES = Uri.parse("content://"
			+ AUTHORITY + "/" + TABLE_RATED_PICTURES);
	public static final Uri CONTENT_URI_PROD = Uri.parse("content://"
			+ AUTHORITY + "/" + TABLE_PROD);
	public static final Uri CONTENT_URI_RATED_INFO = Uri.parse("content://"
			+ AUTHORITY + "/" + TABLE_RATED_INFO);
	public static final Uri CONTENT_URI_RATED_NAMES = Uri.parse("content://"
			+ AUTHORITY + "/" + TABLE_RATED_NAMES);
	public static final Uri CONTENT_URI_RATED_TAGS = Uri.parse("content://"
			+ AUTHORITY + "/" + TABLE_RATED_TAGS);

	// projection Maps
	private static HashMap<String, String> sProjectionMapProds;
	private static HashMap<String, String> sProjectionMapRatedInfo;
	private static HashMap<String, String> sProjectionMapRatedPictures;
	private static HashMap<String, String> sProjectionMapRatedNames;
	private static HashMap<String, String> sProjectionMapRatedTags;

	// UriMatcher
	public static final int MATCH_P = 1;
	public static final int MATCH_RI = 2;
	public static final int MATCH_RN = 3;
	public static final int MATCH_RT = 4;
	public static final int MATCH_RP = 5;

	private static final UriMatcher sUriMatcher;

	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(AUTHORITY, TABLE_PROD, MATCH_P);
		sUriMatcher.addURI(AUTHORITY, TABLE_RATED_INFO, MATCH_RI);
		sUriMatcher.addURI(AUTHORITY, TABLE_RATED_NAMES, MATCH_RN);
		sUriMatcher.addURI(AUTHORITY, TABLE_RATED_TAGS, MATCH_RT);
		sUriMatcher.addURI(AUTHORITY, TABLE_RATED_PICTURES, MATCH_RP);

		sProjectionMapProds = new HashMap<String, String>();
		sProjectionMapProds.put(PRODUCT_ID, PRODUCT_ID);
		sProjectionMapProds.put(NAME, NAME);
		sProjectionMapProds.put(PICTURE, PICTURE);
		sProjectionMapProds.put(LOCATION_NAME, LOCATION_NAME);
		sProjectionMapProds.put(LOCATION_LAT, LOCATION_LAT);
		sProjectionMapProds.put(LOCATION_LONG, LOCATION_LONG);
		sProjectionMapProds.put(PRICE, PRICE);
		sProjectionMapProds.put(RATING, RATING);
		sProjectionMapProds.put(TAGS, TAGS);

		sProjectionMapRatedInfo = new HashMap<String, String>();
		sProjectionMapRatedInfo.put(RATED_INFO_ID, RATED_INFO_ID);
		sProjectionMapRatedInfo.put(RATED_INFO_VALUE, RATED_INFO_VALUE);

		sProjectionMapRatedPictures = new HashMap<String, String>();
		sProjectionMapRatedPictures.put(RATED_PICTURES_ID, RATED_PICTURES_ID);
		sProjectionMapRatedPictures.put(RATED_PICTURES_VALUE,
				RATED_PICTURES_VALUE);

		sProjectionMapRatedNames = new HashMap<String, String>();
		sProjectionMapRatedNames.put(RATED_NAMES_ID, RATED_NAMES_ID);
		sProjectionMapRatedNames.put(RATED_NAMES_VALUE, RATED_NAMES_VALUE);

		sProjectionMapRatedTags = new HashMap<String, String>();
		sProjectionMapRatedTags.put(RATED_TAGS_ID, RATED_TAGS_ID);
		sProjectionMapRatedTags.put(RATED_TAGS_VALUE, RATED_TAGS_VALUE);
	}

	private static class DatabaseHelper extends SQLiteOpenHelper {

		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL("create table " + TABLE_PROD + " (" + PRODUCT_ID
					+ " VARCHAR(20) PRIMARY KEY, " + NAME + " VARCHAR(40), "
					+ LOCATION_NAME + " VARCHAR(50), " + LOCATION_LAT
					+ " NUMBER, " + LOCATION_LONG + " NUMBER, " + PICTURE
					+ " VARCHAR(256), " + PRICE + " FLOAT, " + RATING
					+ " INTEGER, " + TAGS + " TEXT);");

			db.execSQL("create table " + TABLE_RATED_INFO + " ("
					+ RATED_INFO_ID + " INTEGER PRIMARY KEY, "
					+ RATED_INFO_VALUE + " INTEGER);");

			db.execSQL("create table " + TABLE_RATED_NAMES + " ("
					+ RATED_NAMES_ID + " INTEGER PRIMARY KEY, "
					+ RATED_NAMES_VALUE + " INTEGER);");

			db.execSQL("create table " + TABLE_RATED_PICTURES + " ("
					+ RATED_PICTURES_ID + " INTEGER PRIMARY KEY, "
					+ RATED_PICTURES_VALUE + " INTEGER);");

			db.execSQL("create table " + TABLE_RATED_TAGS + " ("
					+ RATED_TAGS_ID + " INTEGER PRIMARY KEY, "
					+ RATED_TAGS_VALUE + " INTEGER);");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS " + TABLE_PROD);
			db.execSQL("DROP TABLE IF EXISTS " + TABLE_RATED_INFO);
			db.execSQL("DROP TABLE IF EXISTS " + TABLE_RATED_NAMES);
			db.execSQL("DROP TABLE IF EXISTS " + TABLE_RATED_TAGS);
			db.execSQL("DROP TABLE IF EXISTS " + TABLE_RATED_PICTURES);
			onCreate(db);
		}
	}

	private DatabaseHelper dbHelper;

	@Override
	public boolean onCreate() {
		dbHelper = new DatabaseHelper(getContext());
		return true;
	}

	@Override
	public String getType(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case MATCH_P:
			return CONTENT_TYPE_PROD;
		case MATCH_RI:
			return CONTENT_TYPE_INFO;
		case MATCH_RN:
			return CONTENT_TYPE_NAMES;
		case MATCH_RT:
			return CONTENT_TYPE_TAGS;
		case MATCH_RP:
			return CONTENT_TYPE_PICTURES;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

		switch (sUriMatcher.match(uri)) {
		case MATCH_P:
			qb.setTables(TABLE_PROD);
			qb.setProjectionMap(sProjectionMapProds);
			break;
		case MATCH_RI:
			qb.setTables(TABLE_RATED_INFO);
			qb.setProjectionMap(sProjectionMapRatedInfo);
			break;
		case MATCH_RN:
			qb.setTables(TABLE_RATED_NAMES);
			qb.setProjectionMap(sProjectionMapRatedNames);
			break;
		case MATCH_RT:
			qb.setTables(TABLE_RATED_TAGS);
			qb.setProjectionMap(sProjectionMapRatedTags);
			break;
		case MATCH_RP:
			qb.setTables(TABLE_RATED_PICTURES);
			qb.setProjectionMap(sProjectionMapRatedPictures);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		final SQLiteDatabase db = dbHelper.getReadableDatabase();
		final Cursor c = qb.query(db, projection, selection, selectionArgs,
				null, null, sortOrder);

		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}

	@Override
	public Uri insert(Uri uri, ContentValues initialValues) {
		ContentValues values;

		if (initialValues != null) {
			values = new ContentValues(initialValues);
		} else {
			values = new ContentValues();
		}

		final SQLiteDatabase db = dbHelper.getWritableDatabase();
		long rowId;
		switch (sUriMatcher.match(uri)) {
		case MATCH_P:
			rowId = db.insert(TABLE_PROD, PRODUCT_ID, values);
			if (rowId > 0) {
				final Uri noteUri = ContentUris.withAppendedId(
						CONTENT_URI_PROD, rowId);
				getContext().getContentResolver().notifyChange(noteUri, null);
				return noteUri;
			}
			break;
		case MATCH_RI:
			rowId = db.insert(TABLE_RATED_INFO, RATED_INFO_ID, values);
			if (rowId > 0) {
				final Uri noteUri = ContentUris.withAppendedId(
						CONTENT_URI_RATED_INFO, rowId);
				getContext().getContentResolver().notifyChange(noteUri, null);
				return noteUri;
			}
			break;
		case MATCH_RN:
			rowId = db.insert(TABLE_RATED_NAMES, RATED_NAMES_ID, values);
			if (rowId > 0) {
				final Uri noteUri = ContentUris.withAppendedId(
						CONTENT_URI_RATED_NAMES, rowId);
				getContext().getContentResolver().notifyChange(noteUri, null);
				return noteUri;
			}
			break;
		case MATCH_RT:
			rowId = db.insert(TABLE_RATED_TAGS, RATED_TAGS_ID, values);
			if (rowId > 0) {
				final Uri noteUri = ContentUris.withAppendedId(
						CONTENT_URI_RATED_TAGS, rowId);
				getContext().getContentResolver().notifyChange(noteUri, null);
				return noteUri;
			}
			break;
		case MATCH_RP:
			rowId = db.insert(TABLE_RATED_PICTURES, RATED_PICTURES_ID, values);
			if (rowId > 0) {
				final Uri noteUri = ContentUris.withAppendedId(
						CONTENT_URI_RATED_PICTURES, rowId);
				getContext().getContentResolver().notifyChange(noteUri, null);
				return noteUri;
			}
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		throw new SQLException("Failed to insert row into " + uri);
	}

	@Override
	public int update(Uri uri, ContentValues values, String where,
			String[] whereArgs) {
		final SQLiteDatabase db = dbHelper.getWritableDatabase();
		int count = 0;
		switch (sUriMatcher.match(uri)) {
		case MATCH_P:
			count = db.update(TABLE_PROD, values, where, whereArgs);
			break;
		case MATCH_RI:
			count = db.update(TABLE_RATED_INFO, values, where, whereArgs);
			break;
		case MATCH_RN:
			count = db.update(TABLE_RATED_NAMES, values, where, whereArgs);
			break;
		case MATCH_RT:
			count = db.update(TABLE_RATED_TAGS, values, where, whereArgs);
			break;
		case MATCH_RP:
			count = db.update(TABLE_RATED_PICTURES, values, where, whereArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

	@Override
	public int delete(Uri uri, String where, String[] whereArgs) {
		final SQLiteDatabase db = dbHelper.getWritableDatabase();
		int count;
		switch (sUriMatcher.match(uri)) {
		case MATCH_P:
			count = db.delete(TABLE_PROD, where, whereArgs);
			break;
		case MATCH_RI:
			count = db.delete(TABLE_RATED_INFO, where, whereArgs);
			break;
		case MATCH_RN:
			count = db.delete(TABLE_RATED_NAMES, where, whereArgs);
			break;
		case MATCH_RT:
			count = db.delete(TABLE_RATED_TAGS, where, whereArgs);
			break;
		case MATCH_RP:
			count = db.delete(TABLE_RATED_PICTURES, where, whereArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}
}
